#include "nodemanagerpanel.h"
#include "nodemanager/wnodemanager.h"
#include "locomanager/locomanager.h"
#include "cmainframe.h"
#include "createnodedialog.h"
#include <wx/mousestate.h>

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ParamEditPanel::ParamEditPanel(wxWindow* parent)
    : wxPanel(parent, wxID_ANY),
      mBasenode(NULL),
      m_NameTextEditFinished(false),
      m_deviceidTextEditFinished(false),
      m_coordTextEditFinished(false),
      m_switchStateTextEditFinished(false)
{
    InitUI();
}

ParamEditPanel::~ParamEditPanel()
{

}

void ParamEditPanel::InitUI()
{
    // 创建控件
    m_nodeTypeLabel = new wxStaticText(this, wxID_ANY, wxT("结点类型:"));
    m_nodeTypeCombo = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
                                     CreateChoiceArray({wxT("道岔"), wxT("信号灯"), wxT("挂接点")}), wxCB_READONLY);

    m_nodeNameLabel = new wxStaticText(this, wxID_ANY, wxT("结点名称:"));
    m_nodeNameText = new wxTextCtrl(this, wxID_ANY, "",
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTE_PROCESS_ENTER);

    m_deviceidLabel = new wxStaticText(this, wxID_ANY, wxT("设备ID:"));
    m_deviceidText = new wxTextCtrl(this, wxID_ANY, "",
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTE_PROCESS_ENTER);

    m_coordLabel = new wxStaticText(this, wxID_ANY, wxT("坐标信息 (x,y):"));
    m_coordText = new wxTextCtrl(this, wxID_ANY, "",
                                 wxDefaultPosition, wxDefaultSize,
                                 wxTE_PROCESS_ENTER);

    m_signalDirLabel = new wxStaticText(this, wxID_ANY, wxT("信号灯方向:"));
    m_signalDirCombo = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
                                      CreateChoiceArray({wxT("文本在pos的左侧(向左延伸)"), wxT("文本在pos的右侧(向右延伸)")}), wxCB_READONLY);

    m_signalRouteLabel = new wxStaticText(this, wxID_ANY, wxT("信号灯进路类型:"));
    m_signalRouteCombo = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
                                        CreateChoiceArray({wxT("带左边轨道"), wxT("带右边轨道"), wxT("两边都不带")}), wxCB_READONLY);

    m_switchStateLabel = new wxStaticText(this, wxID_ANY, wxT("道岔状态:"));
    m_switchStateText = new wxTextCtrl(this, wxID_ANY, "",
                                       wxDefaultPosition, wxDefaultSize,
                                       wxTE_PROCESS_ENTER);

    // 布局
    wxFlexGridSizer* mainSizer = new wxFlexGridSizer(7, 2, 5, 5);
    mainSizer->AddGrowableCol(1);
    mainSizer->SetFlexibleDirection(wxBOTH);

    mainSizer->Add(m_nodeTypeLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_nodeTypeCombo, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_nodeNameLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_nodeNameText, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_deviceidLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_deviceidText, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_coordLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_coordText, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_signalDirLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_signalDirCombo, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_signalRouteLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_signalRouteCombo, 1, wxEXPAND | wxALL, 5);

    mainSizer->Add(m_switchStateLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
    mainSizer->Add(m_switchStateText, 1, wxEXPAND | wxALL, 5);

    SetSizerAndFit(mainSizer);

    m_nodeNameText->Bind(wxEVT_TEXT, &ParamEditPanel::OnNameTextChanged, this);
    m_coordText->Bind(wxEVT_TEXT, &ParamEditPanel::OnCoordTextChanged, this);
    m_switchStateText->Bind(wxEVT_TEXT, &ParamEditPanel::OnSwitchStateChanged, this);
    m_nodeNameText->Bind(wxEVT_KILL_FOCUS, &ParamEditPanel::OnNameTextKillFocus, this);
    m_coordText->Bind(wxEVT_KILL_FOCUS, &ParamEditPanel::OnCoordTextKillFocus, this);
    m_switchStateText->Bind(wxEVT_KILL_FOCUS, &ParamEditPanel::OnSwitchStateKillFocus, this);
    m_nodeNameText->Bind(wxEVT_TEXT_ENTER, &ParamEditPanel::OnNameTextEnter, this);
    m_coordText->Bind(wxEVT_TEXT_ENTER, &ParamEditPanel::OnCoordTextEnter, this);
    m_switchStateText->Bind(wxEVT_TEXT_ENTER, &ParamEditPanel::OnSwitchStateTextEnter, this);

    m_deviceidText->Bind(wxEVT_TEXT, &ParamEditPanel::OnDeviceIDChanged, this);
    m_deviceidText->Bind(wxEVT_KILL_FOCUS, &ParamEditPanel::OnDeviceIDKillFocus, this);
    m_deviceidText->Bind(wxEVT_TEXT_ENTER, &ParamEditPanel::OnDeviceIDEnter, this);

    m_nodeTypeCombo->Bind(wxEVT_COMBOBOX, &ParamEditPanel::OnNodeTypeComboBoxSelected, this);
    m_signalDirCombo->Bind(wxEVT_COMBOBOX, &ParamEditPanel::OnSignalDirComboBoxSelected, this);
    m_signalRouteCombo->Bind(wxEVT_COMBOBOX, &ParamEditPanel::OnSignalRouteComboBoxSelected, this);
}

// 重置所有参数
void ParamEditPanel::resetAllData(void)
{
    m_nodeNameText->SetValue("");
    m_coordText->SetValue("");
    m_switchStateText->SetValue("");
}

void ParamEditPanel::OnNodeTypeComboBoxSelected(wxCommandEvent& event)
{
    wxString selectedText = m_nodeTypeCombo->GetStringSelection();
    sig_item_change.emitt(mBasenode,0,m_lastChangedData["node_type"],selectedText);
    m_lastChangedData["node_type"]=selectedText;
}

void ParamEditPanel::OnSignalDirComboBoxSelected(wxCommandEvent& event)
{
    wxString selectedText = m_signalDirCombo->GetStringSelection();
    sig_item_change.emitt(mBasenode,4,m_lastChangedData["signal_direction"],selectedText);
    m_lastChangedData["signal_direction"]=selectedText;
}

void ParamEditPanel::OnSignalRouteComboBoxSelected(wxCommandEvent& event)
{
    wxString selectedText = m_signalRouteCombo->GetStringSelection();
    sig_item_change.emitt(mBasenode,5,m_lastChangedData["signal_route_type"],selectedText);
    m_lastChangedData["signal_route_type"]=selectedText;
}

void ParamEditPanel::OnDeviceIDChanged(wxCommandEvent& event)
{
    m_deviceidTextEditFinished = true;
}

void ParamEditPanel::OnDeviceIDKillFocus(wxFocusEvent& event)
{
    if(m_switchStateTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_deviceidText->GetValue());
        sig_item_change.emitt(mBasenode,2,m_lastChangedData["deviceid"],m_deviceidText->GetValue());
        m_lastChangedData["deviceid"]=m_deviceidText->GetValue();
        m_switchStateTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnDeviceIDEnter(wxCommandEvent& event)
{
    if(m_switchStateTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_deviceidText->GetValue());
        sig_item_change.emitt(mBasenode,2,m_lastChangedData["deviceid"],m_deviceidText->GetValue());
        m_lastChangedData["deviceid"]=m_deviceidText->GetValue();
        m_switchStateTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnNameTextChanged(wxCommandEvent& event)
{
    m_NameTextEditFinished = true;
}

void ParamEditPanel::OnCoordTextChanged(wxCommandEvent& event)
{
    m_coordTextEditFinished = true;
}

void ParamEditPanel::OnSwitchStateChanged(wxCommandEvent& event)
{
    m_switchStateTextEditFinished = true;
}

void ParamEditPanel::OnNameTextEnter(wxCommandEvent& event)
{
    if(m_NameTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_nodeNameText->GetValue());
        sig_item_change.emitt(mBasenode,1,m_lastChangedData["node_name"],m_nodeNameText->GetValue());
        m_lastChangedData["node_name"]=m_nodeNameText->GetValue();
        m_NameTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnCoordTextEnter(wxCommandEvent& event)
{
    if(m_coordTextEditFinished)
    {
        if(!IsFloatColonFloatFormatRegex(m_coordText->GetValue()))
        {
            wxMessageBox(wxT("输入格式不正确,请重新输入."),wxT("警告"));
            return;
        }

        sig_item_change.emitt(mBasenode,3,m_lastChangedData["coordinates"],m_coordText->GetValue());
        m_lastChangedData["coordinates"]=m_coordText->GetValue();
        m_coordTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnSwitchStateTextEnter(wxCommandEvent& event)
{
    if(m_switchStateTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_switchStateText->GetValue());
        sig_item_change.emitt(mBasenode,6,m_lastChangedData["switch_state"],m_switchStateText->GetValue());
        m_lastChangedData["switch_state"]=m_switchStateText->GetValue();
        m_switchStateTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnNameTextKillFocus(wxFocusEvent& event)
{
    if(m_NameTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_nodeNameText->GetValue());
        sig_item_change.emitt(mBasenode,1,m_lastChangedData["node_name"],m_nodeNameText->GetValue());
        m_lastChangedData["node_name"]=m_nodeNameText->GetValue();
        m_NameTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnCoordTextKillFocus(wxFocusEvent& event)
{
    if(m_coordTextEditFinished)
    {
        if(!IsFloatColonFloatFormatRegex(m_coordText->GetValue()))
        {
            wxMessageBox(wxT("输入格式不正确,请重新输入."),wxT("警告"));
            return;
        }

        //wxLogMessage("Editing completed with text: %s", m_coordText->GetValue());
        sig_item_change.emitt(mBasenode,3,m_lastChangedData["coordinates"],m_coordText->GetValue());
        m_lastChangedData["coordinates"]=m_coordText->GetValue();
        m_coordTextEditFinished = false;
    }
    event.Skip();
}

void ParamEditPanel::OnSwitchStateKillFocus(wxFocusEvent& event)
{
    if(m_switchStateTextEditFinished)
    {
        //wxLogMessage("Editing completed with text: %s", m_switchStateText->GetValue());
        sig_item_change.emitt(mBasenode,6,m_lastChangedData["switch_state"],m_switchStateText->GetValue());
        m_lastChangedData["switch_state"]=m_switchStateText->GetValue();
        m_switchStateTextEditFinished = false;
    }
    event.Skip();
}

// 获取所有参数数据
std::map<wxString, wxString> ParamEditPanel::GetData() const
{
    std::map<wxString, wxString> data;
    data["node_type"] = m_nodeTypeCombo->GetValue();
    data["deviceid"] = m_deviceidText->GetValue();
    data["node_name"] = m_nodeNameText->GetValue();
    data["coordinates"] = m_coordText->GetValue();
    data["signal_direction"] = m_signalDirCombo->GetValue();
    data["signal_route_type"] = m_signalRouteCombo->GetValue();
    data["switch_state"] = m_switchStateText->GetValue();

    return data;
}

// 设置参数数据
void ParamEditPanel::SetData(const std::map<wxString, wxString>& data)
{
    m_lastChangedData = data;

    if (data.count("node_type")) m_nodeTypeCombo->SetValue(data.at("node_type"));
    if (data.count("node_name")) m_nodeNameText->SetValue(data.at("node_name"));
    if (data.count("deviceid")) m_deviceidText->SetValue(data.at("deviceid"));
    if (data.count("coordinates")) m_coordText->SetValue(data.at("coordinates"));
    if (data.count("signal_direction")) m_signalDirCombo->SetValue(data.at("signal_direction"));
    if (data.count("signal_route_type")) m_signalRouteCombo->SetValue(data.at("signal_route_type"));
    if (data.count("switch_state")) m_switchStateText->SetValue(data.at("switch_state"));

    if(data.at("node_type") == wxT("道岔"))
    {
        m_nodeTypeCombo->Enable(false);
        m_nodeNameText->Enable(false);
        m_deviceidText->Enable(true);
        m_coordText->Enable(true);
        m_signalDirCombo->Enable(false);
        m_signalRouteCombo->Enable(false);
        m_switchStateText->Enable(true);
    }
    else if(data.at("node_type") == wxT("信号灯"))
    {
        m_nodeTypeCombo->Enable(false);
        m_nodeNameText->Enable(false);
        m_deviceidText->Enable(true);
        m_coordText->Enable(true);
        m_signalDirCombo->Enable(true);
        m_signalRouteCombo->Enable(true);
        m_switchStateText->Enable(false);
    }
    else if(data.at("node_type") == wxT("挂接点"))
    {
        m_nodeTypeCombo->Enable(false);
        m_nodeNameText->Enable(false);
        m_coordText->Enable(true);
        m_deviceidText->Enable(true);
        m_signalDirCombo->Enable(false);
        m_signalRouteCombo->Enable(false);
        m_switchStateText->Enable(false);
    }
}

// 挂接道岔改变信号槽
void ParamEditPanel::sig_ProcessItemChanged(NodeManagerPanel *pNodeManagerPanel)
{
    // 挂接道岔改变信号槽
    sig_item_change.connect(pNodeManagerPanel,&NodeManagerPanel::slot_ProcessItemChanged);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

MountPointsPanel::MountPointsPanel(wxWindow *parent)
    : wxPanel(parent),
      mBasenode(NULL)
{
    // 创建主垂直布局
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

    // 创建DataViewCtrl
    m_dvc = new wxDataViewCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE);

    // 创建数据存储
    m_store = new wxDataViewListStore();
    m_dvc->AssociateModel(m_store);

    mainSizer->Add(m_dvc, 1, wxEXPAND);

    SetSizer(mainSizer);

    m_dvc->AppendTextColumn(wxT("挂结点名称"), 0, wxDATAVIEW_CELL_EDITABLE, 90);

    wxArrayString choices1;

    std::map<wxString,WBaseNode*> allnodes = WNodeManager::getSingleton().getAllNodes();
    std::map<wxString,WBaseNode*>::iterator iternode = allnodes.begin();
    for(;iternode != allnodes.end();++iternode)
        choices1.Add((*iternode).second->getName());

    m_choicescolumn = new wxDataViewColumn(
        wxT("挂接结点"),
        new wxDataViewChoiceRenderer(choices1, wxDATAVIEW_CELL_EDITABLE, wxALIGN_LEFT),
        1,
        80);
    m_dvc->AppendColumn(m_choicescolumn);

    m_dvc->AppendTextColumn(wxT("挂结点坐标"), 2, wxDATAVIEW_CELL_EDITABLE, 100);
    m_dvc->AppendTextColumn(wxT("等级"), 3, wxDATAVIEW_CELL_EDITABLE, 80);

    wxArrayString choices;
    choices.Add(wxT("左"));
    choices.Add(wxT("右"));

    wxDataViewColumn* column = new wxDataViewColumn(
        wxT("方向"),
        new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_LEFT),
        4,
        80);
    m_dvc->AppendColumn(column);

    this->Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &MountPointsPanel::OnEditingDone, this, m_dvc->GetId());
    m_dvc->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &MountPointsPanel::OnRightClick, this);
}

MountPointsPanel::~MountPointsPanel()
{

}

// 重置所有参数
void MountPointsPanel::resetAllData(void)
{
    m_store->DeleteAllItems();
}

void MountPointsPanel::OnRightClick(wxDataViewEvent& event)
{
    wxDataViewItem item = event.GetItem();
    if (item.IsOk())
    {
        wxVariant decvalue;
        m_dvc->GetModel()->GetValue(decvalue, item, 0);

        // 创建并显示菜单
        wxMenu menu;
        menu.Append(IDD_PARAMEDIT_DELETENODE,
                    wxString::Format(wxT("删除 '%s'"),decvalue.GetString()));
        menu.Bind(wxEVT_MENU, &MountPointsPanel::OnDeleteMountPoint, this, IDD_PARAMEDIT_DELETENODE);

        m_dvc->PopupMenu(&menu, event.GetPosition());
    }
    else
    {
        // 创建并显示菜单
        wxMenu menu;
        menu.Append(IDD_PARAMEDIT_ADD_MOUNTNODE,wxT("添加挂载点"));

        menu.Bind(wxEVT_MENU, &MountPointsPanel::OnAddNewMountPoint, this, IDD_PARAMEDIT_ADD_MOUNTNODE);

        m_dvc->PopupMenu(&menu, event.GetPosition());
    }

    event.Skip();
}

void MountPointsPanel::OnDeleteMountPoint(wxCommandEvent& event)
{
    wxMessageDialog dialog(
        this,
        wxT("您是否要删除当前挂载点?"),
        wxT("警告"),
        wxYES_NO | wxICON_QUESTION | wxICON_WARNING
        );

    if (dialog.ShowModal() == wxID_YES && mBasenode != NULL)
    {
        wxVariant decvalue;
        m_dvc->GetModel()->GetValue(decvalue, m_dvc->GetSelection(), 0);

        if(mBasenode->deleteMountPoint(decvalue.GetString()))
        {
            wxVariant nodevalue;
            m_dvc->GetModel()->GetValue(nodevalue, m_dvc->GetSelection(), 1);

            WBaseNode *decBaseNode = WNodeManager::getSingleton().getNodeByName(nodevalue.GetString());
            if(decBaseNode != NULL && decBaseNode != mBasenode)
            {
                // 清除其它结点中与之关联的挂载点
                decBaseNode->deleteMountPointByNode(mBasenode);
            }

            m_store->DeleteItem(m_store->GetRow(m_dvc->GetSelection()));
        }
    }
}

void MountPointsPanel::OnAddNewMountPoint(wxCommandEvent& event)
{
    CreateNodeDialog dlg(this, wxT("创建挂载点"));
    if (dlg.ShowModal() == wxID_OK && mBasenode != NULL)
    {
        wxString nodeName = dlg.GetNodeName();

        // 检测这个结点是否存在系统中
        if(mBasenode->isExistMountPoint(nodeName))
        {
            wxMessageBox(wxString::Format(wxT("'%s'已经存在系统中，无法添加!"),nodeName),
                         wxT("警告"),
                         wxOK | wxICON_WARNING, this);
            return;
        }

        //this->reloadAllNodes();

        if(mBasenode->addMountPoint(nodeName,tagMountPoint(nodeName,wxRealPoint(0.0f,0.0f),mBasenode,1,0)))
        {
            wxVector<wxVariant> mountdata;
            mountdata.push_back(nodeName);
            mountdata.push_back(mBasenode->getName());
            mountdata.push_back(wxString::Format("%.2f;%.2f",0.0f,0.0f));
            mountdata.push_back(wxString::Format("%d",1));
            mountdata.push_back(wxT("左"));

            this->addData(mountdata);
        }
    }
}

void MountPointsPanel::OnEditingDone(wxDataViewEvent& event)
{
    event.Skip();

    wxDataViewItem item = event.GetItem();
    int col = event.GetColumn();

    if (event.IsEditCancelled())
        return;

    wxVariant oldvalue;
    m_dvc->GetModel()->GetValue(oldvalue, item, col);
    wxVariant newvalue = event.GetValue();

    if(oldvalue.GetString() != newvalue.GetString() &&
       mBasenode != NULL &&
       newvalue.GetString() != mBasenode->getName())
    {
        wxVariant namevalue;
        m_dvc->GetModel()->GetValue(namevalue, item, 0);

        tagMountPoint *pMountPoint = mBasenode->getMountPointByName(namevalue.GetString());
        if(pMountPoint != NULL)
        {
            if(col == 0)
            {
                if(!mBasenode->updateMountPointName(oldvalue.GetString(),newvalue.GetString()))
                {
                    wxMessageBox(wxString::Format(wxT("'%s' 改名为 '%s' 失败!"),oldvalue.GetString(),newvalue.GetString()),wxT("警告"));
                }
            }
            else if(col == 1)
            {
                // 清除以前结点中与之关联的挂载点
                WBaseNode* oldBaseNode = WNodeManager::getSingleton().getNodeByName(oldvalue.GetString());
                if(oldBaseNode && oldBaseNode != mBasenode)
                    oldBaseNode->deleteMountPointByNode(mBasenode);

                pMountPoint->node = WNodeManager::getSingleton().getNodeByName(newvalue.GetString());

                if(pMountPoint->node)
                {
                    wxString mPointName = wxString::Format(wxT("挂载_%s"),mBasenode->getName());
                    wxRealPoint mPointPos = wxRealPoint(0.0f,0.0f);
                    MountDirection mPointMountDirection = (pMountPoint->direction == MountDirection::DIRECTION_LEFT ? MountDirection::DIRECTION_RIGHT : MountDirection::DIRECTION_LEFT);

                    // 信号灯的话，取第一个挂结点的位置
                    if(pMountPoint->node->getNodeType() == NodeType::NODE_SIGNAL &&
                       !pMountPoint->node->getAllMountPoints().empty())
                    {
                        mPointPos = (*pMountPoint->node->getAllMountPoints().begin()).second.pos;
                    }

                    // 在新结点中加入与之关联的挂载点
                    pMountPoint->node->addMountPoint(mPointName,
                                                     tagMountPoint(mPointName,
                                                                   mPointPos,
                                                                   mBasenode,
                                                                   1,
                                                                   mPointMountDirection));
                }
            }
            else if(col == 2)
            {
                if(!IsFloatColonFloatFormatRegex(newvalue.GetString()))
                {
                    wxMessageBox(wxT("输入格式不正确,请重新输入."),wxT("警告"));
                    return;
                }

                wxVector<double> dummys = getFloatColonFloatFormat(newvalue.GetString());

                pMountPoint->pos = wxRealPoint(dummys[0],dummys[1]);

                if(mBasenode->getNodeType() == NodeType::NODE_SIGNAL)
                {
                    pMountPoint->screenpos = wxRealPoint((mBasenode->getWorkingRect().GetTopLeft().x+mBasenode->getWorkingRect().GetWidth() * (pMountPoint->pos.x / 100.0f)),
                                                         (mBasenode->getWorkingRect().GetTopLeft().y+mBasenode->getWorkingRect().GetHeight() * (pMountPoint->pos.y / 100.0f)));

                    WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>(mBasenode);
                    if(pWSignalLampNode != NULL)
                        pWSignalLampNode->changeWorkingRect(WNodeManager::getSingleton().getWorkingRect());
                }
                else
                {
                    pMountPoint->screenpos = wxRealPoint((mBasenode->getWorkingRect().GetTopLeft().x+mBasenode->getWorkingRect().GetWidth() * (mBasenode->getPosition().x / 100.0f) + pMountPoint->pos.x),
                                             (mBasenode->getWorkingRect().GetTopLeft().y+mBasenode->getWorkingRect().GetHeight() * (mBasenode->getPosition().y / 100.0f)+pMountPoint->pos.y));
                }

                WNodeManager::getSingleton().computerNodeMountAngles(mBasenode);
            }
            else if(col == 3)
            {
                wxRegEx regex("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
                if(!regex.Matches(newvalue.GetString()))
                {
                    wxMessageBox(wxT("输入格式不正确,请重新输入."),wxT("警告"));
                    return;
                }

                long val = 0;
                newvalue.GetString().ToLong(&val);

                pMountPoint->level = val;
            }
            else if(col == 4)
            {
                pMountPoint->direction = (newvalue.GetString() == "左" ? 0 : 1);
            }
        }
    }
}

void MountPointsPanel::clearAllData(void)
{
    m_store->DeleteAllItems();
}

// 重新加载所有的结点
void MountPointsPanel::reloadAllNodes(void)
{
    m_dvc->DeleteColumn(m_choicescolumn);

    wxArrayString choices1;

    std::map<wxString,WBaseNode*> allnodes = WNodeManager::getSingleton().getAllNodes();
    std::map<wxString,WBaseNode*>::iterator iternode = allnodes.begin();
    for(;iternode != allnodes.end();++iternode)
        choices1.Add((*iternode).second->getName());

    m_choicescolumn = new wxDataViewColumn(
        wxT("挂接结点"),
        new wxDataViewChoiceRenderer(choices1, wxDATAVIEW_CELL_EDITABLE, wxALIGN_LEFT),
        1,
        70);
    m_dvc->InsertColumn(1,m_choicescolumn);

    m_dvc->Refresh();
}

void MountPointsPanel::addData(const wxVector<wxVariant> data)
{
    m_store->AppendItem(data);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

NodeManagerPanel::NodeManagerPanel(wxWindow *parent)
    : wxPanel(parent)
{
    // 创建主垂直布局
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* mountSizer = new wxBoxSizer(wxVERTICAL);

    m_ParamEditPanel = new ParamEditPanel(this);
    m_MountPointsPanel = new MountPointsPanel(this);

    m_ParamEditPanel->sig_ProcessItemChanged(this);

    // 创建DataViewCtrl
    m_dvc = new wxDataViewCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE);

    // 创建数据存储
    m_store = new wxDataViewListStore();
    m_dvc->AssociateModel(m_store);

    mountSizer->Add(m_ParamEditPanel, 1, wxEXPAND);
    mountSizer->Add(m_MountPointsPanel, 1, wxEXPAND);

    panelSizer->Add(m_dvc, 3, wxEXPAND);
    panelSizer->Add(mountSizer, 1, wxEXPAND);

    mainSizer->Add(panelSizer, 1, wxEXPAND);

    SetSizer(mainSizer);

    m_dvc->AppendTextColumn(wxT("结点类型"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 80);
    m_dvc->AppendTextColumn(wxT("结点名称"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 80);
    m_dvc->AppendTextColumn(wxT("设备ID"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 80);
    m_dvc->AppendTextColumn(wxT("坐标信息"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 100);
    m_dvc->AppendTextColumn(wxT("信号灯名称方向"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 200);
    m_dvc->AppendTextColumn(wxT("信号灯进路类型"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 120);
    m_dvc->AppendTextColumn(wxT("道岔状态"), m_dvc->GetColumnCount(), wxDATAVIEW_CELL_ACTIVATABLE, 400);

    // 在创建控件后绑定事件
    m_dvc->Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, &NodeManagerPanel::OnItemActivated, this);
    m_dvc->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &NodeManagerPanel::OnSelectionChanged, this);
    m_dvc->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &NodeManagerPanel::OnRightClick, this);
}

NodeManagerPanel::~NodeManagerPanel()
{

}

void NodeManagerPanel::slot_ProcessItemChanged(WBaseNode *pBasenode,int itemindex,wxString olddata,wxString newdata)
{
    if(pBasenode == NULL || olddata == newdata) return;

    // 获取当前选中项
    wxDataViewItem selected = m_dvc->GetSelection();

    if (selected.IsOk())
    {
        const wxDataViewColumn* column = m_dvc->GetColumn(itemindex);

        m_store->SetValue(wxVariant(newdata), selected, column->GetModelColumn());
        m_store->ItemChanged(selected);
    }

    switch(itemindex)
    {
    case 1:    // 更改名称
    {
        if(!WNodeManager::getSingleton().getNodeByName(newdata))
        {

        }
    }
        break;
    case 2:    // 更改设备ID
    {
        int deviceID = 0;
        newdata.ToInt(&deviceID);

        pBasenode->setDeviceID(deviceID);
    }
        break;
    case 3:    // 更改坐标
    {
        wxVector<double> tmpcoords = getFloatColonFloatFormat(newdata);
        if(tmpcoords.size() == 2)
        {
            pBasenode->setPosition(wxRealPoint(tmpcoords[0],tmpcoords[1]));

            tagSectNode* pSectNode = WNodeManager::getSingleton().getSectByNode(pBasenode);
            if(pSectNode != NULL)
            {
                // 重新计算所有的股道
                LocoManager::getSingleton().changeWorkingRect(pSectNode->sectname);
            }
        }
    }
        break;
    case 4:    // 更改信号灯方向
    {
        if(pBasenode->getNodeType() == NodeType::NODE_SIGNAL)
        {
            WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>(pBasenode);
            if(pWSignalLampNode)
            {
                pWSignalLampNode->setNameAlignment(newdata == wxT("文本在pos的左侧(向左延伸)") ? TextAlignment::LEFT : TextAlignment::RIGHT);

                WNodeManager::getSingleton().computerNodeMountAngles(pWSignalLampNode);
            }
        }
    }
        break;
    case 5:    // 更改信号灯进路类型
    {
        if(pBasenode->getNodeType() == NodeType::NODE_SIGNAL)
        {
            WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>(pBasenode);
            if(pWSignalLampNode)
            {
                pWSignalLampNode->setRouteType(newdata == wxT("带左边轨道") ? SLRouteType::ROUTE_LEFT :
                                                (newdata == wxT("带右边轨道") ? SLRouteType::ROUTE_RIGHT : SLRouteType::ROUTE_NULL));
            }
        }
    }
        break;
    case 6:    // 更改道岔状态
    {
        if(pBasenode->getNodeType() == NodeType::NODE_SWITCH)
        {
            WSwitchNode *pWSwitchNode = static_cast<WSwitchNode*>(pBasenode);
            if(pWSwitchNode)
            {
                wxArrayString switchstates = SplitString(newdata,";");
                if(switchstates.size() == 2)
                {
                    for(int i=0;i<switchstates.size();i++)
                    {
                        wxArrayString switchstates1 = SplitString(switchstates[i],":");
                        if(switchstates1.size() == 2 &&
                            (switchstates1[0] == wxT("定位") || switchstates1[0] == wxT("反位")))
                        {
                            wxArrayString switchstates2 = SplitString(switchstates1[1],"-");
                            if(switchstates2.size() == 2)
                            {
                                if(!pWSwitchNode->initSwitchState(switchstates1[0] == wxT("定位") ? SwitchState::POSITIVE : SwitchState::NEGATIVE,
                                                                   switchstates2[0],
                                                                   switchstates2[1]))
                                {
                                    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                                                             wxString::Format("初始道岔状态失败:%s %s-%s",
                                                                             switchstates1[0],
                                                                             switchstates2[0],
                                                                             switchstates2[1]).ToUTF8().data());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
        break;
    default:
        break;
    }
}

void NodeManagerPanel::OnRightClick(wxDataViewEvent& event)
{
    wxDataViewItem item = event.GetItem();
    if (item.IsOk() && m_BaseNode != NULL)
    {
        // 创建并显示菜单
        wxMenu menu;
        menu.Append(IDD_PARAMEDIT_DELETENODE,
                    wxString::Format(wxT("删除 '%s'"),m_BaseNode->getName()));
        menu.Bind(wxEVT_MENU, &NodeManagerPanel::OnDeleteItem, this, IDD_PARAMEDIT_DELETENODE);

        m_dvc->PopupMenu(&menu, event.GetPosition());
    }
    else
    {
        // 创建并显示菜单
        wxMenu menu;
        menu.Append(IDD_PARAMEDIT_ADD_MOUNTNODE,wxT("添加挂结点"));
        menu.Append(IDD_PARAMEDIT_ADD_SIGNALLAMP,wxT("添加信号灯"));
        menu.Append(IDD_PARAMEDIT_ADD_SWITCH,wxT("添加道岔"));

        menu.Bind(wxEVT_MENU, &NodeManagerPanel::OnAddNewMountNode, this, IDD_PARAMEDIT_ADD_MOUNTNODE);
        menu.Bind(wxEVT_MENU, &NodeManagerPanel::OnAddNewSignalLamp, this, IDD_PARAMEDIT_ADD_SIGNALLAMP);
        menu.Bind(wxEVT_MENU, &NodeManagerPanel::OnAddNewSwitch, this, IDD_PARAMEDIT_ADD_SWITCH);

        m_dvc->PopupMenu(&menu, event.GetPosition());
    }

    event.Skip();
}

void NodeManagerPanel::addData(const wxVector<wxVariant> data)
{
    m_store->AppendItem(data);
}

void NodeManagerPanel::OnSelectionChanged(wxDataViewEvent& event)
{
    // 获取当前选中的项目
    wxDataViewItem selectedItem = m_dvc->GetSelection();

    if (selectedItem.IsOk()) {
        // 获取模型
        wxDataViewModel* model = m_dvc->GetModel();

        std::map<wxString, wxString> data;

        // 获取第一列的值
        wxVariant value;
        model->GetValue(value, selectedItem, 0);
        data["node_type"] = value.GetString();
        model->GetValue(value, selectedItem, 1);
        data["node_name"] = value.GetString();
        model->GetValue(value, selectedItem, 2);
        data["deviceid"] = value.GetString();
        model->GetValue(value, selectedItem, 3);
        data["coordinates"] = value.GetString();
        model->GetValue(value, selectedItem, 4);
        data["signal_direction"] = value.GetString();
        model->GetValue(value, selectedItem, 5);
        data["signal_route_type"] = value.GetString();
        model->GetValue(value, selectedItem, 6);
        data["switch_state"] = value.GetString();

        m_ParamEditPanel->SetData(data);

        m_BaseNode = WNodeManager::getSingleton().getNodeByName(data["node_name"]);
        if(m_BaseNode)
        {
            m_ParamEditPanel->setBaseNode(m_BaseNode);
            m_MountPointsPanel->setBaseNode(m_BaseNode);

            m_MountPointsPanel->clearAllData();
            m_MountPointsPanel->reloadAllNodes();

            std::map<wxString,tagMountPoint> tmpMountPoints = m_BaseNode->getAllMountPoints();
            std::map<wxString,tagMountPoint>::iterator iter = tmpMountPoints.begin();
            for(;iter != tmpMountPoints.end();++iter)
            {
                wxVector<wxVariant> mountdata;
                mountdata.push_back((*iter).second.name);
                mountdata.push_back((*iter).second.node != NULL ? (*iter).second.node->getName() : "");
                mountdata.push_back(wxString::Format("%.2f;%.2f",(*iter).second.pos.x,(*iter).second.pos.y));
                mountdata.push_back(wxString::Format("%d",(*iter).second.level));
                mountdata.push_back((*iter).second.direction == 0 ? wxT("左") : wxT("右"));

                m_MountPointsPanel->addData(mountdata);
            }
        }
    }
}

void NodeManagerPanel::addBaseNode(WBaseNode* pbasenode)
{
    if(pbasenode == NULL) return;

    wxVector<wxVariant> decdata;
    switch(pbasenode->getNodeType())
    {
    case NodeType::NODE_SWITCH:
        decdata.push_back(wxT("道岔"));
        break;
    case NodeType::NODE_SIGNAL:
        decdata.push_back(wxT("信号灯"));
        break;
    case NodeType::NODE_MOUNT:
        decdata.push_back(wxT("挂接点"));
        break;
    default:
        break;
    }

    decdata.push_back(pbasenode->getName());
    decdata.push_back(wxString::Format("%d",pbasenode->getDeviceID()));
    decdata.push_back(wxString::Format("%.2f;%.2f",pbasenode->getPosition().x,pbasenode->getPosition().y));

    if(pbasenode->getNodeType() == NodeType::NODE_SIGNAL)
    {
        WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>(pbasenode);
        if(pWSignalLampNode)
        {
            switch(pWSignalLampNode->getNameAlignment())
            {
            case TextAlignment::RIGHT:
                decdata.push_back(wxT("文本在pos的右侧(向右延伸)"));
                break;
            case TextAlignment::LEFT:
                decdata.push_back(wxT("文本在pos的左侧(向左延伸)"));
                break;
            default:
                break;
            }

            switch(pWSignalLampNode->getRouteType())
            {
            case SLRouteType::ROUTE_LEFT:
                decdata.push_back(wxT("带左边轨道"));
                break;
            case SLRouteType::ROUTE_RIGHT:
                decdata.push_back(wxT("带右边轨道"));
                break;
            case SLRouteType::ROUTE_NULL:
                decdata.push_back(wxT("两边都不带"));
                break;
            default:
                break;
            }
        }
    }
    else
    {
        decdata.push_back("");
        decdata.push_back("");
    }

    if(pbasenode->getNodeType() == NodeType::NODE_SWITCH)
    {
        WSwitchNode *pWSwitchNode = static_cast<WSwitchNode*>(pbasenode);
        if(pWSwitchNode)
        {
            wxString decString;
            std::map<SwitchState,SwitchStateMounts> decMounts = pWSwitchNode->getAllSwitchStateMounts();
            std::map<SwitchState,SwitchStateMounts>::iterator iter = decMounts.begin();
            for(;iter != decMounts.end();++iter)
            {
                wxString stateName = (*iter).first == SwitchState::POSITIVE ? wxT("定位") : wxT("反位");
                wxString tmpString = wxString::Format(wxT("%s:%s-%s;"),
                                                      stateName,
                                                      (*iter).second.startMount->name,
                                                      (*iter).second.endMount->name);
                decString += tmpString;
            }

            if(decString.size() > 0)
                decString = decString.Mid(0,decString.size()-1);

            decdata.push_back(decString);
        }
    }
    else
    {
        decdata.push_back("");
    }

    this->addData(decdata);
}

void NodeManagerPanel::OnAddNewMountNode(wxCommandEvent& event)
{
    CreateNodeDialog dlg(this, wxT("创建挂结点"));
    if (dlg.ShowModal() == wxID_OK)
    {
        wxString nodeName = dlg.GetNodeName();

        // 检测这个结点是否存在系统中
        if(WNodeManager::getSingleton().getNodeByName(nodeName))
        {
            wxMessageBox(wxString::Format(wxT("'%s'已经存在系统中，无法添加!"),nodeName),
                         wxT("警告"),
                         wxOK | wxICON_WARNING, this);
            return;
        }

        WMountNode* pMountNode = WNodeManager::getSingleton().addMountNode(nodeName,wxRealPoint(50.0f,50.0f));
        if(pMountNode)
        {
            this->addBaseNode(pMountNode);
        }
    }
}

void NodeManagerPanel::OnAddNewSignalLamp(wxCommandEvent& event)
{
    CreateNodeDialog dlg(this, wxT("创建信号灯"));
    if (dlg.ShowModal() == wxID_OK)
    {
        wxString nodeName = dlg.GetNodeName();

        // 检测这个结点是否存在系统中
        if(WNodeManager::getSingleton().getNodeByName(nodeName))
        {
            wxMessageBox(wxString::Format(wxT("'%s'已经存在系统中，无法添加!"),nodeName),
                         wxT("警告"),
                         wxOK | wxICON_WARNING, this);
            return;
        }

        /// 添加一个信号灯
        WSignalLampNode *pSignalLampNode = WNodeManager::getSingleton().addSignalLamp(nodeName,wxRealPoint(0.0f,0.0f));
        if(pSignalLampNode)
        {
            pSignalLampNode->addMountPoint(wxT("左挂载点"),tagMountPoint(wxT("左挂载点"),
                                                                     wxRealPoint(50.0f,50.0f),
                                                                     pSignalLampNode,
                                                                     1,
                                                                     0));
            pSignalLampNode->addMountPoint(wxT("右挂载点"),tagMountPoint(wxT("右挂载点"),
                                                                     wxRealPoint(50.0f,50.0f),
                                                                     pSignalLampNode,
                                                                     1,
                                                                     1));

            this->addBaseNode(pSignalLampNode);
        }
    }
}

void NodeManagerPanel::OnAddNewSwitch(wxCommandEvent& event)
{
    CreateNodeDialog dlg(this, wxT("创建道岔"));
    if (dlg.ShowModal() == wxID_OK)
    {
        wxString nodeName = dlg.GetNodeName();

        // 检测这个结点是否存在系统中
        if(WNodeManager::getSingleton().getNodeByName(nodeName))
        {
            wxMessageBox(wxString::Format(wxT("'%s'已经存在系统中，无法添加!"),nodeName),
                         wxT("警告"),
                         wxOK | wxICON_WARNING, this);
            return;
        }

        /// 添加一个道岔
        WSwitchNode* pSwitchNode = WNodeManager::getSingleton().addSwitch(nodeName,wxRealPoint(50.0f,50.0f));
        if(pSwitchNode)
        {
            pSwitchNode->addMountPoint(wxT("左挂载点"),tagMountPoint(wxT("左挂载点"),
                                                                     wxRealPoint(0.0f,0.0f),
                                                                     pSwitchNode,
                                                                     1,
                                                                     0));
            pSwitchNode->addMountPoint(wxT("右挂载点1"),tagMountPoint(wxT("右挂载点1"),
                                                                     wxRealPoint(0.0f,0.0f),
                                                                     pSwitchNode,
                                                                     1,
                                                                     1));
            pSwitchNode->addMountPoint(wxT("右挂载点2"),tagMountPoint(wxT("右挂载点2"),
                                                                  wxRealPoint(0.0f,0.0f),
                                                                  pSwitchNode,
                                                                  1,
                                                                  1));

            this->addBaseNode(pSwitchNode);
        }
    }
}

void NodeManagerPanel::OnDeleteItem(wxCommandEvent& event)
{
    // 弹出确认对话框
    wxMessageDialog dialog(
        this,
        wxT("您是否要删除当前结点?"),
        wxT("警告"),
        wxYES_NO | wxICON_QUESTION | wxICON_WARNING
        );

    if (dialog.ShowModal() == wxID_YES && m_BaseNode != NULL)
    {
        if(WNodeManager::getSingleton().deleteNodeByName(m_BaseNode->getName()))
        {
            m_store->DeleteItem(m_store->GetRow(m_dvc->GetSelection()));
            m_ParamEditPanel->resetAllData();
            m_MountPointsPanel->resetAllData();
        }
    }

    event.Skip();
}

void NodeManagerPanel::OnItemActivated(wxDataViewEvent& event)
{
    wxDataViewItem item = event.GetItem();

    if (item.IsOk()) {

    }
}
